package it.unibo.refolding.pico;

import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.Parser;
import org.codehaus.jremoting.server.monitors.ConsoleServerMonitor;
import org.codehaus.jremoting.server.transports.SocketServer;

public class NanoDriverServer {

  private static final Logger logger = Logger.getLogger(NanoDriverServer.class.getSimpleName());

  /**
   * @param args
   * @throws ParseException
   */
  public static void main(String[] args) throws ParseException {
    Options options = new Options();
    Option driverTypeOption = NanoDriverUtil.createDriverTypeOption();
    // The host is the network interface on which to bind.
    Option nanoDriverHostOption = NanoDriverUtil.createNanoDriverHostOption();
    Option nanoDriverPortOption = NanoDriverUtil.createNanoDriverPortOption();
    Option nanoDriverClassOption = NanoDriverUtil.createNanoDriverClassOption();
    Option forceRecordOption = NanoDriverUtil.createForceRecordOption();

    options.addOption(driverTypeOption);
    options.addOption(nanoDriverHostOption);
    options.addOption(nanoDriverPortOption);
    options.addOption(nanoDriverClassOption);
    options.addOption(forceRecordOption);

    Parser parser = new GnuParser();
    CommandLine line = parser.parse(options, args);

    String typeName = line.getOptionValue(driverTypeOption.getOpt());
    String nanoDriverClassname = line.getOptionValue(nanoDriverClassOption.getOpt());
    boolean forceRecord = Boolean.parseBoolean(line.getOptionValue(forceRecordOption.getOpt()));
    String nanoDriverHost = line.getOptionValue(nanoDriverHostOption.getOpt());
    int nanoDriverPort = Integer.parseInt(line.getOptionValue(nanoDriverPortOption.getOpt()));

    final NanoDriverConfig config;
    if (NanoDriverUtil.isFakeNanoDriver(nanoDriverClassname)) {
      config = null;
    } else {
      DriverType type = DriverType.of(typeName);
      switch (type) {
      case STRIP_CHART:
        config = NanoDriverUtil.createStripChartRefoldingRobotConfig(forceRecord);
        break;
      case PLAIN_REFOLDING:
        config = NanoDriverUtil.createPlainRefoldingRobotConfig(forceRecord);
        break;
      case APPROACH_RETRACTION:
        config = NanoDriverUtil.createApproachRetractionRobotConfig(forceRecord);
        break;
      case FETCH_REFOLD_BREAK:
        config = NanoDriverUtil.createFetchRefoldBreakRobotConfig(forceRecord);
        break;
      default:
        throw new IllegalArgumentException(type.toString());
      }
    }
    NanoDriver nanoDriver = NanoDriverUtil.localNanoDriver(nanoDriverClassname, config);

    SocketServer server = new SocketServer(new ConsoleServerMonitor(), new InetSocketAddress(
      nanoDriverHost, nanoDriverPort));
    server.setPruneSessionsInterval((int) TimeUnit.SECONDS.convert(7, TimeUnit.DAYS));
    server.setPruneStaleLongerThan((int) TimeUnit.MILLISECONDS.convert(7, TimeUnit.DAYS));
    server.publish(nanoDriver, "it.unibo.refolding.pico.RemoteNanoDriver", NanoDriver.class);
    server.start();
    logger.info("Ready.");
  }
}
